package com.cencat.route.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cencat.common.result.Result;
import com.cencat.route.entity.Route;
import com.cencat.route.service.RouteService;
import com.cencat.route.vo.RouteQueryVO;
import com.cencat.route.vo.RouteStatisticsVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.List;

/**
 * 路线管理控制器
 * 
 * @author cencat
 * @since 2024-01-01
 */
@Slf4j
@RestController
@RequestMapping("/api/route/route")
@RequiredArgsConstructor
@Tag(name = "路线管理", description = "路线信息的增删改查和业务操作")
public class RouteController {

    private final RouteService routeService;

    @GetMapping("/page")
    @Operation(summary = "分页查询路线", description = "根据条件分页查询路线信息")
    public Result<Page<Route>> getRoutePage(
            @Parameter(description = "页码", example = "1") @RequestParam(defaultValue = "1") Long current,
            @Parameter(description = "每页大小", example = "10") @RequestParam(defaultValue = "10") Long size,
            @Parameter(description = "查询条件") RouteQueryVO query) {
        try {
            Page<Route> page = new Page<>(current, size);
            Page<Route> result = routeService.selectRoutePage(page, query);
            return Result.success(result);
        } catch (Exception e) {
            log.error("分页查询路线失败: {}", e.getMessage(), e);
            return Result.error("分页查询路线失败: " + e.getMessage());
        }
    }

    @GetMapping("/list")
    @Operation(summary = "查询路线列表", description = "根据条件查询路线列表")
    public Result<List<Route>> getRouteList(@Parameter(description = "查询条件") RouteQueryVO query) {
        try {
            List<Route> result = routeService.selectRouteList(query);
            return Result.success(result);
        } catch (Exception e) {
            log.error("查询路线列表失败: {}", e.getMessage(), e);
            return Result.error("查询路线列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/{id}")
    @Operation(summary = "根据ID查询路线", description = "根据路线ID查询详细信息")
    public Result<Route> getRouteById(@Parameter(description = "路线ID") @PathVariable Long id) {
        try {
            Route route = routeService.getById(id);
            if (route == null) {
                return Result.error("路线不存在");
            }
            return Result.success(route);
        } catch (Exception e) {
            log.error("查询路线详情失败: {}", e.getMessage(), e);
            return Result.error("查询路线详情失败: " + e.getMessage());
        }
    }

    @PostMapping
    @Operation(summary = "新增路线", description = "创建新的路线信息")
    public Result<Boolean> createRoute(@Parameter(description = "路线信息") @Valid @RequestBody Route route) {
        try {
            boolean result = routeService.save(route);
            return result ? Result.success(true) : Result.error("新增路线失败");
        } catch (Exception e) {
            log.error("新增路线失败: {}", e.getMessage(), e);
            return Result.error("新增路线失败: " + e.getMessage());
        }
    }

    @PutMapping
    @Operation(summary = "更新路线", description = "更新路线信息")
    public Result<Boolean> updateRoute(@Parameter(description = "路线信息") @Valid @RequestBody Route route) {
        try {
            boolean result = routeService.updateById(route);
            return result ? Result.success(true) : Result.error("更新路线失败");
        } catch (Exception e) {
            log.error("更新路线失败: {}", e.getMessage(), e);
            return Result.error("更新路线失败: " + e.getMessage());
        }
    }

    @DeleteMapping("/{id}")
    @Operation(summary = "删除路线", description = "根据ID删除路线")
    public Result<Boolean> deleteRoute(@Parameter(description = "路线ID") @PathVariable Long id) {
        try {
            boolean result = routeService.removeById(id);
            return result ? Result.success(true) : Result.error("删除路线失败");
        } catch (Exception e) {
            log.error("删除路线失败: {}", e.getMessage(), e);
            return Result.error("删除路线失败: " + e.getMessage());
        }
    }

    @PutMapping("/batch/status")
    @Operation(summary = "批量更新路线状态", description = "批量更新路线状态")
    public Result<Boolean> batchUpdateRouteStatus(
            @Parameter(description = "路线ID列表") @RequestBody List<Long> ids,
            @Parameter(description = "状态") @RequestParam String status,
            @Parameter(description = "更新人ID") @RequestParam Long updatedBy) {
        try {
            boolean result = routeService.batchUpdateRouteStatus(ids, status, updatedBy);
            return result ? Result.success(true) : Result.error("批量更新路线状态失败");
        } catch (Exception e) {
            log.error("批量更新路线状态失败: {}", e.getMessage(), e);
            return Result.error("批量更新路线状态失败: " + e.getMessage());
        }
    }

    @PutMapping("/batch/publish-status")
    @Operation(summary = "批量更新发布状态", description = "批量更新路线发布状态")
    public Result<Boolean> batchUpdatePublishStatus(
            @Parameter(description = "路线ID列表") @RequestBody List<Long> ids,
            @Parameter(description = "发布状态") @RequestParam String publishStatus,
            @Parameter(description = "更新人ID") @RequestParam Long updatedBy) {
        try {
            boolean result = routeService.batchUpdatePublishStatus(ids, publishStatus, updatedBy);
            return result ? Result.success(true) : Result.error("批量更新发布状态失败");
        } catch (Exception e) {
            log.error("批量更新发布状态失败: {}", e.getMessage(), e);
            return Result.error("批量更新发布状态失败: " + e.getMessage());
        }
    }

    @PutMapping("/batch/priority")
    @Operation(summary = "批量更新优先级", description = "批量更新路线优先级")
    public Result<Boolean> batchUpdatePriority(
            @Parameter(description = "路线ID列表") @RequestBody List<Long> ids,
            @Parameter(description = "优先级") @RequestParam Integer priority,
            @Parameter(description = "更新人ID") @RequestParam Long updatedBy) {
        try {
            boolean result = routeService.batchUpdatePriority(ids, priority, updatedBy);
            return result ? Result.success(true) : Result.error("批量更新优先级失败");
        } catch (Exception e) {
            log.error("批量更新优先级失败: {}", e.getMessage(), e);
            return Result.error("批量更新优先级失败: " + e.getMessage());
        }
    }

    @PutMapping("/batch/price")
    @Operation(summary = "批量更新价格", description = "批量更新路线价格")
    public Result<Boolean> batchUpdatePrice(
            @Parameter(description = "路线ID列表") @RequestBody List<Long> ids,
            @Parameter(description = "价格") @RequestParam BigDecimal price,
            @Parameter(description = "更新人ID") @RequestParam Long updatedBy) {
        try {
            boolean result = routeService.batchUpdatePrice(ids, price, updatedBy);
            return result ? Result.success(true) : Result.error("批量更新价格失败");
        } catch (Exception e) {
            log.error("批量更新价格失败: {}", e.getMessage(), e);
            return Result.error("批量更新价格失败: " + e.getMessage());
        }
    }

    @GetMapping("/statistics")
    @Operation(summary = "获取路线统计信息", description = "获取路线相关统计数据")
    public Result<RouteStatisticsVO> getRouteStatistics() {
        try {
            RouteStatisticsVO result = routeService.getRouteStatistics();
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取路线统计信息失败: {}", e.getMessage(), e);
            return Result.error("获取路线统计信息失败: " + e.getMessage());
        }
    }

    @PostMapping("/smart-match")
    @Operation(summary = "智能匹配路线", description = "根据条件智能匹配合适的路线")
    public Result<String> smartMatchRoutes(
            @Parameter(description = "匹配条件") @RequestParam String matchCriteria,
            @Parameter(description = "最大匹配数量") @RequestParam(defaultValue = "10") Integer maxMatches) {
        try {
            String result = routeService.smartMatchRoutes(matchCriteria, maxMatches);
            return Result.success(result);
        } catch (Exception e) {
            log.error("智能匹配路线失败: {}", e.getMessage(), e);
            return Result.error("智能匹配路线失败: " + e.getMessage());
        }
    }

    @GetMapping("/hot")
    @Operation(summary = "获取热门路线列表", description = "获取热门的路线列表")
    public Result<List<Route>> getHotRoutes(
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "20") Integer limit) {
        try {
            List<Route> result = routeService.getHotRoutes(limit);
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取热门路线列表失败: {}", e.getMessage(), e);
            return Result.error("获取热门路线列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/recommended")
    @Operation(summary = "获取推荐路线列表", description = "获取推荐的路线列表")
    public Result<List<Route>> getRecommendedRoutes(
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "20") Integer limit) {
        try {
            List<Route> result = routeService.getRecommendedRoutes(limit);
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取推荐路线列表失败: {}", e.getMessage(), e);
            return Result.error("获取推荐路线列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/active")
    @Operation(summary = "获取活跃路线列表", description = "获取活跃的路线列表")
    public Result<List<Route>> getActiveRoutes(
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "50") Integer limit) {
        try {
            List<Route> result = routeService.getActiveRoutes(limit);
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取活跃路线列表失败: {}", e.getMessage(), e);
            return Result.error("获取活跃路线列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/published")
    @Operation(summary = "获取已发布路线列表", description = "获取已发布的路线列表")
    public Result<List<Route>> getPublishedRoutes(
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "50") Integer limit) {
        try {
            List<Route> result = routeService.getPublishedRoutes(limit);
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取已发布路线列表失败: {}", e.getMessage(), e);
            return Result.error("获取已发布路线列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/high-priority")
    @Operation(summary = "获取高优先级路线列表", description = "获取高优先级的路线列表")
    public Result<List<Route>> getHighPriorityRoutes(
            @Parameter(description = "最低优先级") @RequestParam(defaultValue = "8") Integer minPriority,
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "30") Integer limit) {
        try {
            List<Route> result = routeService.getHighPriorityRoutes(minPriority, limit);
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取高优先级路线列表失败: {}", e.getMessage(), e);
            return Result.error("获取高优先级路线列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/new")
    @Operation(summary = "获取新创建路线列表", description = "获取最近创建的路线列表")
    public Result<List<Route>> getNewRoutes(
            @Parameter(description = "天数") @RequestParam(defaultValue = "7") Integer days,
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "30") Integer limit) {
        try {
            List<Route> result = routeService.getNewRoutes(days, limit);
            return Result.success(result);
        } catch (Exception e) {
            log.error("获取新创建路线列表失败: {}", e.getMessage(), e);
            return Result.error("获取新创建路线列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/check/exists/{id}")
    @Operation(summary = "检查路线是否存在", description = "根据ID检查路线是否存在")
    public Result<Boolean> checkRouteExists(@Parameter(description = "路线ID") @PathVariable Long id) {
        try {
            boolean result = routeService.checkRouteExists(id);
            return Result.success(result);
        } catch (Exception e) {
            log.error("检查路线是否存在失败: {}", e.getMessage(), e);
            return Result.error("检查路线是否存在失败: " + e.getMessage());
        }
    }

    @GetMapping("/check/code")
    @Operation(summary = "检查路线编码是否存在", description = "检查路线编码是否已被使用")
    public Result<Boolean> checkRouteCodeExists(
            @Parameter(description = "路线编码") @RequestParam String routeCode,
            @Parameter(description = "排除的路线ID") @RequestParam(required = false) Long excludeId) {
        try {
            boolean result = routeService.checkRouteCodeExists(routeCode, excludeId);
            return Result.success(result);
        } catch (Exception e) {
            log.error("检查路线编码是否存在失败: {}", e.getMessage(), e);
            return Result.error("检查路线编码是否存在失败: " + e.getMessage());
        }
    }

    @GetMapping("/check/name")
    @Operation(summary = "检查路线名称是否存在", description = "检查路线名称是否已被使用")
    public Result<Boolean> checkRouteNameExists(
            @Parameter(description = "路线名称") @RequestParam String routeName,
            @Parameter(description = "排除的路线ID") @RequestParam(required = false) Long excludeId) {
        try {
            boolean result = routeService.checkRouteNameExists(routeName, excludeId);
            return Result.success(result);
        } catch (Exception e) {
            log.error("检查路线名称是否存在失败: {}", e.getMessage(), e);
            return Result.error("检查路线名称是否存在失败: " + e.getMessage());
        }
    }

    @GetMapping("/calculate/distance")
    @Operation(summary = "计算路线距离", description = "计算路线的总距离")
    public Result<BigDecimal> calculateRouteDistance(
            @Parameter(description = "路线ID") @RequestParam Long routeId) {
        try {
            BigDecimal result = routeService.calculateRouteDistance(routeId);
            return Result.success(result);
        } catch (Exception e) {
            log.error("计算路线距离失败: {}", e.getMessage(), e);
            return Result.error("计算路线距离失败: " + e.getMessage());
        }
    }

    @GetMapping("/estimate/time")
    @Operation(summary = "预估路线时间", description = "预估路线的行驶时间")
    public Result<Integer> estimateRouteTime(
            @Parameter(description = "路线ID") @RequestParam Long routeId) {
        try {
            Integer result = routeService.estimateRouteTime(routeId);
            return Result.success(result);
        } catch (Exception e) {
            log.error("预估路线时间失败: {}", e.getMessage(), e);
            return Result.error("预估路线时间失败: " + e.getMessage());
        }
    }

    @PutMapping("/update-statistics/{id}")
    @Operation(summary = "更新路线统计信息", description = "更新路线的统计数据")
    public Result<Boolean> updateRouteStatistics(
            @Parameter(description = "路线ID") @PathVariable Long id,
            @Parameter(description = "更新人ID") @RequestParam Long updatedBy) {
        try {
            boolean result = routeService.updateRouteStatistics(id, updatedBy);
            return result ? Result.success(true) : Result.error("更新路线统计信息失败");
        } catch (Exception e) {
            log.error("更新路线统计信息失败: {}", e.getMessage(), e);
            return Result.error("更新路线统计信息失败: " + e.getMessage());
        }
    }

    @PutMapping("/publish/{id}")
    @Operation(summary = "发布路线", description = "发布路线")
    public Result<Boolean> publishRoute(
            @Parameter(description = "路线ID") @PathVariable Long id,
            @Parameter(description = "发布人ID") @RequestParam Long publishedBy) {
        try {
            boolean result = routeService.publishRoute(id, publishedBy);
            return result ? Result.success(true) : Result.error("发布路线失败");
        } catch (Exception e) {
            log.error("发布路线失败: {}", e.getMessage(), e);
            return Result.error("发布路线失败: " + e.getMessage());
        }
    }

    @PutMapping("/unpublish/{id}")
    @Operation(summary = "取消发布路线", description = "取消发布路线")
    public Result<Boolean> unpublishRoute(
            @Parameter(description = "路线ID") @PathVariable Long id,
            @Parameter(description = "取消发布人ID") @RequestParam Long unpublishedBy) {
        try {
            boolean result = routeService.unpublishRoute(id, unpublishedBy);
            return result ? Result.success(true) : Result.error("取消发布路线失败");
        } catch (Exception e) {
            log.error("取消发布路线失败: {}", e.getMessage(), e);
            return Result.error("取消发布路线失败: " + e.getMessage());
        }
    }

    @PutMapping("/activate/{id}")
    @Operation(summary = "激活路线", description = "激活路线")
    public Result<Boolean> activateRoute(
            @Parameter(description = "路线ID") @PathVariable Long id,
            @Parameter(description = "激活人ID") @RequestParam Long activatedBy) {
        try {
            boolean result = routeService.activateRoute(id, activatedBy);
            return result ? Result.success(true) : Result.error("激活路线失败");
        } catch (Exception e) {
            log.error("激活路线失败: {}", e.getMessage(), e);
            return Result.error("激活路线失败: " + e.getMessage());
        }
    }

    @PutMapping("/deactivate/{id}")
    @Operation(summary = "停用路线", description = "停用路线")
    public Result<Boolean> deactivateRoute(
            @Parameter(description = "路线ID") @PathVariable Long id,
            @Parameter(description = "停用原因") @RequestParam String reason,
            @Parameter(description = "停用人ID") @RequestParam Long deactivatedBy) {
        try {
            boolean result = routeService.deactivateRoute(id, reason, deactivatedBy);
            return result ? Result.success(true) : Result.error("停用路线失败");
        } catch (Exception e) {
            log.error("停用路线失败: {}", e.getMessage(), e);
            return Result.error("停用路线失败: " + e.getMessage());
        }
    }

    @PostMapping("/copy/{id}")
    @Operation(summary = "复制路线", description = "复制现有路线")
    public Result<Boolean> copyRoute(
            @Parameter(description = "路线ID") @PathVariable Long id,
            @Parameter(description = "新路线名称") @RequestParam String newRouteName,
            @Parameter(description = "复制人ID") @RequestParam Long copiedBy) {
        try {
            boolean result = routeService.copyRoute(id, newRouteName, copiedBy);
            return result ? Result.success(true) : Result.error("复制路线失败");
        } catch (Exception e) {
            log.error("复制路线失败: {}", e.getMessage(), e);
            return Result.error("复制路线失败: " + e.getMessage());
        }
    }

    @PutMapping("/optimize/{id}")
    @Operation(summary = "优化路线", description = "优化路线路径")
    public Result<Boolean> optimizeRoute(
            @Parameter(description = "路线ID") @PathVariable Long id,
            @Parameter(description = "优化参数") @RequestParam String optimizationParams,
            @Parameter(description = "优化人ID") @RequestParam Long optimizedBy) {
        try {
            boolean result = routeService.optimizeRoute(id, optimizationParams, optimizedBy);
            return result ? Result.success(true) : Result.error("优化路线失败");
        } catch (Exception e) {
            log.error("优化路线失败: {}", e.getMessage(), e);
            return Result.error("优化路线失败: " + e.getMessage());
        }
    }

}